home *** CD-ROM | disk | FTP | other *** search
/ The Best of MacTutor - S…e Code for Volumes 1 to 5 / The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin / Source Code / #27 (Dec 87) / c daisy printer driver / PDEF0.c < prev    next >
C/C++ Source or Header  |  1987-09-29  |  10KB  |  398 lines

  1. /*
  2.  * LightspeedC source for PDEF 0, routines to implement draft mode printing
  3.  * on a serial device. 
  4.  * Earle R. Horton, September 19, 1987.
  5.  * All rights reserved.
  6.  */
  7.  
  8. #include "prglobals.h"
  9. #include <EventMgr.h>
  10.  
  11. pascal    TPPrPort    myPrOpenDoc();
  12. pascal    void        myPrCloseDoc();
  13. pascal    void        myPrOpenPage();
  14. pascal    void        myPrClosePage();
  15. pascal    void        myStdText();
  16. pascal    int        myStdTextMeas();
  17. void            myClearPage();
  18. Ptr            allocate();
  19. void            free();
  20. void            bcopy();
  21. DPstorage        DrvrStorage();
  22. void            checkabort();
  23.  
  24. main(){
  25.     asm{
  26.         dc.w    ILLEGAL        ;;  So I can find it...
  27.         jmp    myPrOpenDoc
  28.         jmp    myPrCloseDoc
  29.         jmp    myPrOpenPage
  30.         jmp    myPrClosePage
  31.  
  32.     }
  33. }
  34. /*
  35.  * This function is supposed to return a pointer to a specialized GrafPort
  36.  * (a TPrPort) customized for printing.  Due to the paucity of documentation
  37.  * on how to go about this, I do not know whether I am going about this in
  38.  * exactly the right way, but I sure hope so.  I set portBits.bounds for the
  39.  * port to the empty Rect {0,0,0,0} and then install the standard QuickDraw
  40.  * routines as GrafProcs.  In place of StdText, I put my own StdText routine.
  41.  * Hopefully, QuickDraw will keep track of the correct pen location for me,
  42.  * and call my routine whenever it is necessary to draw text.  I just put
  43.  * the text in a big buffer for now, and then print it out when I get called
  44.  * to close the current page.  This takes up some memory, but solves the
  45.  * problem of what to do when the application wants a reverse line feed.
  46.  * Other tasks:
  47.  *    save a copy of the user print record for later use in formatting the 
  48.  *    output page
  49.  *    save a copy of the user print record in the printer resource file
  50.  */
  51. pascal TPPrPort myPrOpenDoc(hPrint,pPrPort,pIOBuf)
  52. THPrint     hPrint;
  53. TPPrPort     pPrPort;
  54. Ptr         pIOBuf;
  55. {
  56. TPPrPort     thisport;
  57. pline        thepage;
  58. Handle        us;
  59. register DPstorage    dsp;
  60. THPrint     savePrint;
  61. PrParam        *pb;
  62.  
  63.     us = (Handle)(GetResource('PDEF',0));
  64.     asm{
  65.         move.l    us,a0
  66.         HLock
  67.     }
  68. /* Assign storage for printing port and page buffer. */
  69.     if((thepage = (pline)allocate((long)(NROWS*sizeof(line)))) == nil){
  70.         PrintErr = iMemFullErr;
  71.         return nil;
  72.     }
  73.     else if(pPrPort == nil){
  74.         if((thisport = (TPPrPort)
  75.             allocate((long)sizeof(TPrPort))) == nil){
  76.             free(thepage);
  77.             PrintErr = iMemFullErr;
  78.             return(nil);
  79.         }
  80.         thisport->fOurPtr = TRUE;
  81.     }
  82.     else {
  83.         thisport = pPrPort;
  84.         thisport->fOurPtr = FALSE;
  85.     }
  86. /* Copy print record into private storage area. */
  87.     dsp = DrvrStorage();
  88.     pb = &dsp->prpb;
  89.         dsp->Print = **hPrint;
  90.     thisport->lGParam4 = (long)thepage;
  91.     dsp->Print.prJob.bJDocLoop = bDraftLoop;
  92.     OpenPort(thisport);
  93. /* Fill out gProcs for this port. */
  94.     SetStdProcs(&thisport->gProcs);
  95.     thisport->gProcs.textProc    =    (QDPtr)myStdText;
  96.     thisport->gProcs.txMeasProc    =    (QDPtr)myStdTextMeas;
  97.  
  98.     thisport->gPort.grafProcs    =    &thisport->gProcs;
  99. /*
  100.  * Set up the port Rect in the proper coordinates, relative to the page
  101.  * and to the paper.
  102.  */
  103.     thisport->gPort.device        =    dsp->Print.prInfo.iDev;
  104.     thisport->gPort.portRect    =    dsp->Print.prInfo.rPage;
  105.     thisport->gPort.portBits.bounds.top =
  106.      thisport->gPort.portBits.bounds.left =
  107.       thisport->gPort.portBits.bounds.bottom =
  108.        thisport->gPort.portBits.bounds.right = 0;
  109.  
  110.     
  111.     SetPort(thisport);
  112. /* Offset the page (portRect) relative to the paper. */
  113.     PortSize
  114.       (dsp->Print.prInfo.rPage.right,dsp->Print.prInfo.rPage.bottom);
  115.     MovePortTo(- dsp->Print.rPaper.left, - dsp->Print.rPaper.top);
  116.     GrafDevice(dsp->Print.prInfo.iDev);
  117.     myClearPage(thepage);
  118.         pb->csCode = iPrDevCtl;        /* Init the printer. */
  119.         pb->lParam1 = lPrReset;        /* Driver code does the work. */
  120.     asm{
  121.         move.l    pb,a0
  122.         PBControl
  123.     }
  124.     dsp->pagenum = 1;
  125.         if(dsp->Print.prJob.pIdleProc == nil)
  126.         dsp->Print.prJob.pIdleProc = (ProcPtr)checkabort;
  127.         savePrint = (THPrint)GetResource('PREC',1);
  128.         if(savePrint != nil){
  129.         LoadResource(savePrint);
  130.         **savePrint = dsp->Print;
  131.         ChangedResource(savePrint);
  132.         ReleaseResource(savePrint);
  133.         }        /* Determine proper margins. */
  134.         dsp->nlines = (dsp->Print.rPaper.bottom - dsp->Print.rPaper.top)/
  135.             CHARHEIGHT;
  136.     return(thisport);
  137. }
  138. pascal void myPrCloseDoc(pPrPort)
  139. TPPrPort    pPrPort;
  140. {
  141. pline        thepage;
  142. Pfg        settings;
  143.  
  144.     free(pPrPort->lGParam4);
  145.     ClosePort(pPrPort);
  146.     if(pPrPort->fOurPtr) free(pPrPort);
  147. }
  148. /* 
  149.  * This routine opens a new page.  Actually, all it does is clear out the
  150.  * array of lines in preparation for more fun with QuickDraw.  I suppose it
  151.  * could also send a reset command to the driver...
  152.  */
  153. pascal void myPrOpenPage(pPrPort,pPageFrame)
  154. TPPrPort    pPrPort;
  155. TPRect        pPageFrame;
  156. {
  157. register DPstorage dsp;
  158.     dsp = DrvrStorage();
  159.     if(pPageFrame != nil)
  160.         *pPageFrame = dsp->Print.prInfo.rPage;
  161.     SetPort(pPrPort);
  162.  
  163.     myClearPage(pPrPort->lGParam4);
  164. }
  165. /*
  166.  * This is the routine which does the actual printing.  QuickDraw calls
  167.  * which have called our StdText substitute routine have filled up a 
  168.  * buffer with lines of text.  Now, we just get the buffer and print it.
  169.  */
  170. pascal void myPrClosePage(pPrPort)
  171. TPPrPort    pPrPort;
  172. {
  173. register DPstorage dsp;
  174. register pline    theline;
  175. register int    i,iocount;
  176. PrParam        *pb;
  177.  
  178.     dsp = DrvrStorage();
  179.     pb = &dsp->prpb;
  180.         if(dsp->pagenum < dsp->Print.prJob.iFstPage){
  181.             dsp->pagenum++;
  182.             return;
  183.         }
  184.         if(dsp->pagenum++ > dsp->Print.prJob.iLstPage){
  185.             PrintErr = iPrAbort;
  186.             if (dsp->preofstr[0] != '\0'){
  187.             pb->csCode = iPrIOCtl;
  188.                 pb->lParam1 = (long)(&dsp->preofstr[1]);
  189.                 pb->lParam2 = (long)dsp->preofstr[0];
  190.                 asm{
  191.                     move.l    pb,a0
  192.                     PBControl
  193.                 }
  194.             }
  195.             return;
  196.     }
  197.         if(dsp->Print.prStl.feed != feedCut || waitnextpage()){
  198.         theline = (pline)pPrPort->lGParam4;
  199.             if (dsp->prtopstr[0] != '\0'){
  200.                 pb->csCode = iPrIOCtl;
  201.                 pb->lParam1 = (long)(&dsp->prtopstr[1]);
  202.                 pb->lParam2 = (long)dsp->prtopstr[0];
  203.                 asm{
  204.                     move.l    pb,a0
  205.                     PBControl
  206.                 }
  207.             }
  208.         for(i=0;dsp->nlines - i;i++){
  209.                 (* dsp->Print.prJob.pIdleProc)();
  210.                 if(PrintErr == iPrAbort)return;
  211.                 if((theline+i)->dirty == DIRTY){
  212.                     iocount = WIDTH;
  213.                     while( (theline+i)->text[--iocount] == ' '){}
  214.                     ++iocount;
  215.                     pb->csCode = iPrIOCtl;
  216.                     pb->lParam1 = 
  217.                         (long)(&(theline+i)->text[0]);
  218.                     pb->lParam2 = (long)iocount;
  219.                 asm{
  220.                     move.l    pb,a0
  221.                     PBControl
  222.                 }
  223.                 }
  224.             pb->csCode = iPrDevCtl;
  225.             if(i < dsp->nlines - 1)
  226.                 pb->lParam1 = lPrLineFeed;
  227.             else pb->lParam1 = lPrPageEnd;
  228.             asm{
  229.                 move.l    pb,a0
  230.                 PBControl
  231.             }
  232.         }
  233.        }
  234.     else PrintErr = iPrAbort;
  235. }
  236. /*
  237.  * All text drawing calls in the TPrPort get sent here.  Find the current
  238.  * pen location and translate it to row and column of the page buffer, 
  239.  * squirt the text into the buffer.
  240.  */
  241. pascal void myStdText(byteCount,textBuf,numer,denom)
  242. int    byteCount;
  243. QDPtr    textBuf;
  244. Point    numer,denom;
  245. {
  246. Point        thepoint;
  247. TPPrPort    tp;
  248. pline        thepage;
  249. int        width;
  250. int    x,y;
  251.     GetPort(&tp);
  252.     if(tp->gPort.device == IDEV10) width = 7;
  253.     else if(tp->gPort.device == IDEV15) width = 5;
  254.     else width = 6;
  255.     thepage = (pline)tp->lGParam4;
  256.     GetPen(&thepoint);
  257. /* (Local is page, Global is paper.) */
  258.     LocalToGlobal(&thepoint);
  259.     x = thepoint.h/width;
  260.     y = thepoint.v/CHARHEIGHT;
  261.     bcopy(textBuf,&((thepage+y)->text[x]),byteCount);
  262.     (thepage+y)->dirty = DIRTY;
  263.     Move(width*byteCount,0);
  264. }
  265. pascal    int    myStdTextMeas(byteCount,textBuf,numer,denom,info)
  266. int    byteCount;
  267. QDPtr    textBuf;
  268. Point    *numer,*denom;
  269. FontInfo *info;
  270. {
  271. TPPrPort    tp;
  272.     GetPort(&tp);
  273.     if(tp->gPort.device == IDEV10)info->widMax = 7;
  274.     else if(tp->gPort.device == IDEV15)info->widMax = 5;
  275.     else info->widMax = 6;
  276.     info->ascent = 9;
  277.     info->descent = 2;
  278.     info->leading = 0;
  279.     numer->v = denom->v = 1;
  280.     denom->h = 6;
  281.     numer->h = info->widMax;
  282.     return (info->widMax * byteCount);
  283. }
  284. void    myClearPage(theline)
  285. pline    theline;
  286. {
  287. int    count;
  288. unsigned char    *ch;
  289.  
  290.     count = NROWS;
  291. clear:
  292.     theline->dirty = ~DIRTY;
  293.     ch = &theline->text[0];
  294.     asm{
  295.         move.l    ch,a0
  296.         move.w    #((WIDTH/4)-1),d0
  297.         move.l    #0x20202020,d1
  298. loop:
  299.         move.l    d1,(a0)+
  300.         dbra    d0,@loop
  301.     }
  302.     if(--count){
  303.         theline++;
  304.         goto clear;
  305.     }
  306. }
  307. Ptr allocate(size)
  308. long size;
  309. {
  310.     asm{
  311.         move.l    size,d0
  312.         NewPtr
  313.         move.l    a0,d0        ;; LightspeedC returns function
  314.     }                /* value in d0. */
  315. }
  316. void free(ptr)
  317. Ptr    ptr;
  318. {
  319.     asm{
  320.         move.l    ptr,a0
  321.         DisposPtr
  322.     }
  323. }
  324. /*
  325.  * A UNIXism.  Want to make something of it?
  326.  */
  327. void bcopy(src,dst,count)
  328. unsigned char *src,*dst;
  329. int count;
  330. {
  331.     asm{
  332.         move.l    src,a0
  333.         move.l    dst,a1
  334.         clr.l    d0
  335.         move.w    count,d0
  336.         BlockMove
  337.     }
  338. }
  339. #define UTableBase 284
  340. /*
  341.  * This function returns a pointer to the printer driver's private
  342.  * storage.  We don't need to lock the Handle, since it is always locked
  343.  * when the driver is open.
  344.  */
  345. DPstorage DrvrStorage()
  346. {
  347. DCtlHandle    ourDCtlEntry;
  348. DHstorage    ourdCtlStorage;
  349.     asm{
  350.         move    #2,d0
  351.         asl.l    #2,d0            ;; d0 = 8L
  352.         move.l    UTableBase,a0        ;; a0 -> base of unit table
  353.         adda    d0,a0            ;; a0 -> second entry
  354.         move.l    (a0),ourDCtlEntry    ;; handle to DCtlEntry[2]
  355.     }
  356.     ourdCtlStorage = (DHstorage)(*ourDCtlEntry)->dCtlStorage;
  357.     return(*ourdCtlStorage);
  358. }
  359. /*
  360.  * Abort printing if command '.' pressed.
  361.  */
  362. void checkabort()
  363. {
  364. EventRecord    myevent;
  365. int        c;
  366.     if (GetNextEvent(keyDownMask, &myevent)){
  367.         if(LoWord(myevent.message & charCodeMask) == '.' &&
  368.                   (myevent.modifiers & cmdKey) ){
  369.                 PrintErr = iPrAbort;
  370.         }
  371.     }
  372. }
  373. /*
  374.  * Modal dialog box: "Insert next sheet."
  375.  */
  376. waitnextpage()
  377. {
  378. DialogPtr sheetdialog;
  379. WindowPtr tempport;
  380. int    itemhit,donetype;
  381. Handle    doneitem;
  382. Rect    donebox;
  383.     if((sheetdialog = GetNewDialog(SHEETDIALOG, 0L,(WindowPtr) -1)) == nil)
  384.         return FALSE;
  385.     InitCursor();
  386.     GetDItem(sheetdialog,DONEITEM,&donetype,&doneitem,&donebox);
  387.     GetPort(&tempport);
  388.     SetPort(sheetdialog);
  389.     PenSize(3,3);
  390.     InsetRect(&donebox,-4,-4);
  391.     FrameRoundRect(&donebox,16,16);
  392.     ModalDialog(0L,&itemhit);
  393.     DisposDialog(sheetdialog);
  394.     SetPort(tempport);
  395.     if(itemhit == STOPITEM) return FALSE;
  396.     return TRUE;
  397. }
  398.